import configparser
import pickle
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_absolute_error,r2_score,mean_squared_error
from sklearn.preprocessing import MinMaxScaler
import pandas as pd

def read_excel(fname):
    df = pd.read_excel('data/'+fname+'.xlsx',index_col = 0)
    df.index = pd.to_datetime(df.index)
    timeseries = df.index.values

    scaler_speed = MinMaxScaler()
    scaler_flow = MinMaxScaler()
    scaler_occu = MinMaxScaler()

    # print (np.array(df['speed']).reshape(-1,1))
    speed = scaler_speed.fit_transform(np.array(df['speed']).reshape(-1,1))
    flow = scaler_flow.fit_transform(np.array(df['flow']).reshape(-1,1))
    occu = scaler_occu.fit_transform(np.array(df['occu']).reshape(-1,1))

    return_dict = {}
    return_dict['speed'] = speed
    return_dict['flow'] = flow
    return_dict['occu'] = occu
    return_dict['scaler_speed'] = scaler_speed
    return_dict['scaler_flow'] = scaler_flow
    return_dict['scaler_occu'] = scaler_occu
    return_dict['time'] = timeseries

    return return_dict

def get_SVR_input(fname,type='speed'):
    # 没有归一化效果更好

    excel_vec = read_excel(fname)

    speed_list = excel_vec['scaler_speed'].inverse_transform(excel_vec['speed']).transpose().tolist()[0]
    flow_list = excel_vec['scaler_flow'].inverse_transform(excel_vec['flow']).transpose().tolist()[0]
    date = excel_vec['time']

    x = []
    y_speed = []
    y_flow = []
    time_log = []

    for i in range(0,len(speed_list),4):
        try:
            vec = [speed_list[i],speed_list[i+1],speed_list[i+2]]
            vec.extend([flow_list[i],flow_list[i+1],flow_list[i+2]])
            x.append(vec)
            y_speed.append(speed_list[i+3])
            y_flow.append(flow_list[i+3])
            time_log.append(date[i+3]) # just for plot

        except IndexError:
            break

    if type=='speed':
        return np.asarray(x), np.asarray(y_speed),np.asarray(time_log),excel_vec['scaler_speed']
    if type=='flow':
        return np.asarray(x), np.asarray(y_flow),np.asarray(time_log),excel_vec['scaler_flow']


    return EOFError

def MAPE(true,pred):
    diff = np.abs(np.array(true) - np.array(pred))
    return np.mean(diff / true)*100

def test():
    speed_x, speed_y,time, scalers = get_SVR_input('test_up','speed')
    flow_x, flow_y,time, scalers = get_SVR_input('test_up','flow')

    pickle_save_path = config["Model"]["pickle_save_path"]

    with open(pickle_save_path + 'svr_speed_model.pickle', "rb") as model_file:
        speed_model = pickle.load(model_file)

    with open(pickle_save_path + 'svr_flow_model.pickle', "rb") as model_file:
        flow_model = pickle.load(model_file)

    # 计算测试得分（决定系数）
    speed_score = speed_model.score(speed_x, speed_y)
    flow_score = flow_model.score(flow_x, flow_y)

    print("测试得分（决定系数） :",speed_score,flow_score)

    predictVelocity = []
    predictFlow = []


    for i in speed_x:
        predictVelocity.append(speed_model.predict([i]).tolist()[0])

    for i in flow_x:
        predictFlow.append(flow_model.predict([i]).tolist()[0])


    print ('speed:')
    print ('mae: ',mean_absolute_error(speed_y,predictVelocity))
    print ('r2 score: ',r2_score(speed_y,predictVelocity))
    print ('mse: ',mean_squared_error(speed_y,predictVelocity))
    print ('mape: ',MAPE(speed_y,predictVelocity))
    print ('\nflow:')
    print ('mae: ',mean_absolute_error(flow_y,predictFlow))
    print ('r2 score: ',r2_score(flow_y,predictFlow))
    print ('mse: ',mean_squared_error(flow_y,predictFlow))
    print ('mape: ',MAPE(flow_y,predictFlow))

    x = range(len(speed_x))

    last=-1
    plt.rcParams['font.family'] = 'SimHei'
    plt.rcParams['font.size'] = 12
    plt.rcParams['axes.unicode_minus'] = False

    fig=plt.figure()
    ax1=fig.add_subplot(2,2,1)
    ax1.plot(x[:last],speed_y[:last],color='#4285F4',label="真实值",linestyle='-')
    ax1.plot(x[:last],predictVelocity[:last],color='#DB4437',label= "预测值",linestyle='--',marker='x')
    ax1.set_xlabel("时间/min")
    ax1.set_ylabel("速度")
    ax1.set_title('PSO-SVR 预测结果')
    ax1.legend(loc="best",framealpha=0.5)

    error=speed_y[:last]-predictVelocity[:last]
    ax2=fig.add_subplot(2,2,2)
    ax2.bar(x[:last],speed_y[:last]-predictVelocity[:last])
    ax2.set_xlabel("时间/min")
    ax2.set_ylabel("绝对误差")
    ax2.set_ylim(-2,2)
    ax2.set_title('平均速度绝对误差')

    ax3=fig.add_subplot(2,2,3)
    ax3.plot(x[:last],flow_y[:last],color='#F4B400',label="真实值",linestyle='-' )
    ax3.plot(x[:last],predictFlow[:last],color='#0F9D58',label= "预测值",linestyle='--',marker='x')
    ax3.set_xlabel("时间/min")
    ax3.set_ylabel("流量")
    ax3.set_title('PSO-SVR 预测结果')

    ax3.legend(loc="best",framealpha=0.5)

    error=flow_y[:last]-predictFlow[:last]
    ax4=fig.add_subplot(2,2,4)
    ax4.bar(x[:last],speed_y[:last]-predictVelocity[:last])
    ax4.set_xlabel("时间/min")
    ax4.set_ylabel("绝对误差")
    ax4.set_ylim(-2,2)
    ax4.set_title('交通流量绝对误差')

    plt.tight_layout()
    plt.subplots_adjust(left=0.08,hspace =0.5)
    plt.show()



if __name__ == "__main__":
    config_file = 'train_pso_svr.config'
    config = configparser.ConfigParser()
    config.read(config_file)
    test()
